package main

import (
	"fmt"
	"github.com/chromedp/chromedp"
	"io"
	"io/ioutil"
	"log"
	"mp4/entity"
	"mp4/util"
	"os"
	"strings"
)

const (
	default_value = 30
)

func main() {
	filePath, _ := os.Getwd()
	filePath = strings.ReplaceAll(filePath, "\\", "/")
	filePath = strings.ReplaceAll(filePath, "//", "/")

	os.Remove(filePath + "/message.log")
	f, err := os.OpenFile("message.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)
	if err != nil {
		return
	}
	defer func() {
		f.Close()
	}()

	// 组合一下即可，os.Stdout代表标准输出流
	multiWriter := io.MultiWriter(os.Stdout, f)
	log.SetOutput(multiWriter)

	log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)

	//filePath := "F:\\work\\go\\download\\mp4\\config"
	log.Println("[" + filePath + "]")

	var entities []entity.DownloadEntity
	entities = util.ReadConfigs(filePath, filePath, entities)

	var filePaths []string
	if nil != entities {
		for index, source := range entities {
			log.Println("=====================================================================")
			log.Println(source.URL, "=======", fmt.Sprintf("%d", index), "=======", source.ConfigPath)
			log.Println("=====================================================================")
			source.TempFileDirPath = source.FileDirPath
			if strings.Index(source.FileDirPath, ":/") == -1 && strings.Index(source.FileDirPath, ":\\") == -1 {
				source.FileDirPath = util.CombinationFielPath(filePath, source.FileDirPath)
			}
			if 0 == source.ChromedpSleep {
				source.ChromedpSleep = util.SLEEP_VALUE
			}

			for i := 0; i < 2; i++ {
				flag := Choose(source, filePaths)
				if flag {
					break
				}
			}
		}
	}

	//flag, paths := util.Synthesis("E:/temp/download/dashidai/content/segmentation/0001", entities[0])
	//if flag {
	//	util.WriteSend(paths, entities[0].AbsolutePath)
	//}

	//util.SysnthesisTsToMp4("E:/temp/temp/content/独步逍遥/0001/content.txt", entities[0], " E:/temp/temp/content/独步逍遥/0001_4_0001_第01集.mp4")
	//util.SegmentationTs("0004_第04集.mp4", entities[0].FileDirPath+"/images", entities[0])
	//util.MerryGoRoundFun("E:\\temp\\temp\\content\\独步逍遥\\segmentation\\第01集", entities[0])

	//util.MerryGoRoundFun("E:\\temp\\temp\\content\\独步逍遥\\segmentation\\第02集", entities[0], "第02集")
	//util.SegmentationTs("0001_1_0001_01.mp4", "E:\\temp\\download\\duanju\\1", entities[0], "0001")
	//util.IdentifyImpage("E:\\temp\\download\\duanju\\1\\0001", entities[0])
	//util.CombTs("E:/temp/download/baifamonv/content/segmentation/0002", "0002_2", entities[0])

}

func Choose(configEntity entity.DownloadEntity, filePaths []string) bool {
	index := configEntity.ChildURLIndex
	var configEntities []string
	pageIndex := 0
	var plaList []entity.PlayListEntity
	var flag bool
	_, plaList, responseEntity := util.ChoosePlayList(configEntity, true)
	num := util.RandomNum(default_value, 1)
	numIndex := 0
	length := len(plaList)
	if length == 0 && !util.IsEmpty(configEntity.M3u8URL) {
		plaList = append(plaList, entity.PlayListEntity{TitleStr: "01", TitleIndex: "01", Index: 1})
		plaList[0].TitleNames = append(plaList[0].TitleNames, "001")
		responseEntity = entity.ResponseEntity{M3u8: configEntity.M3u8URL}
		length = 1
	}
	pageIndex1 := 0
	startIndex := configEntity.StartIndex
	pageIndex1 = configEntity.StartIndex - 1
	if pageIndex1 < 0 {
		pageIndex1 = 0
	}

	for i := pageIndex; i < util.PAGECOUNT; i++ {
		if i == length {
			return true
		}
		if pageIndex1 == length {
			return true
		}

		nextEntty := plaList[pageIndex1]
		pageIndex1++
		if len(nextEntty.TitleNames) == 0 {
			log.Println("没有数据->", configEntity.FileDirPath, configEntity.ConfigPath, "htmlSize:", len(responseEntity.BodyStr))
			return true
		}
		flag, index, configEntities, startIndex = foreachURL(nextEntty, index, configEntity, filePaths, responseEntity, configEntities, startIndex)
		if flag {
			pageIndex++
		} else {
			numIndex++
		}

		flag = num == int32(numIndex)

		if flag {
			_, plaList, responseEntity = util.ChoosePlayList(configEntity, true)
			num = util.RandomNum(default_value, 1)
			pageIndex1 = pageIndex
		}

		log.Println(nextEntty.TitleStr, "\n ---over-->num:", num, "--numIndex:", numIndex, "\n \n")

	}
	return false
}

func foreachURL(nextEntty entity.PlayListEntity, urlIndex int, configEntity entity.DownloadEntity, filePaths []string, responseEntity entity.ResponseEntity,
	configEntities []string, startIndex int) (bool, int, []string, int) {
	titile := fmt.Sprintf(nextEntty.TitleStrFormat, 1)
	urlLengths := len(nextEntty.URLS) - 1

	flag := true
	length := len(nextEntty.URLS)
	index := urlIndex
	var filePath string
	realFilePath := configEntity.FileDirPath + "/" + nextEntty.TitleNames[0] + configEntity.AudioType
	if util.ExistsFile(realFilePath, configEntity) && util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		return flag, index, configEntities, startIndex
	}

	for urlIndex1 := 0; urlIndex1 < length; urlIndex1++ {

		index = cambIndex(index, nextEntty.URLS)
		url := nextEntty.URLS[index]
		flag, filePaths = util.SwitchFileExstsTitle(titile, filePaths, configEntity)
		if flag {
			flag = false
			break
		}

		//start := time.Now()
		if util.IsEmpty(configEntity.M3u8URL) {
			responseEntity = util.SwitchChooseM3u8(configEntity, url)
		} else {
			responseEntity = entity.ResponseEntity{M3u8: configEntity.M3u8URL}
		}

		if len(strings.TrimSpace(responseEntity.M3u8)) > 0 && !util.ExistsFile(realFilePath, configEntity) {
			filePath = configEntity.FileDirPath + "/" + titile + configEntity.AudioType
			if util.ExistsFile(filePath, configEntity) && util.ValidateFileSize2(filePath, configEntity, configEntity.FileMinSize) {
				flag = true
				break
			}

			flag, filePaths = downLoad(responseEntity, configEntity, titile, nextEntty, index)
			flag = util.ExistsFile(filePath, configEntity) && util.ValidateFileSize2(filePath, configEntity, configEntity.FileMinSize)

			if flag {
				flag, filePaths = util.DownloadM3u8Http(responseEntity.M3u8, configEntity, responseEntity, titile)
			}

			flag = util.ExistsFile(filePath, configEntity) && util.ValidateFileSize2(filePath, configEntity, configEntity.FileMinSize)

			if flag {
				startIndex = nextEntty.Index
				chromedp.Sleep(configEntity.ChromedeSleep)
				flag, index, configEntities = downloadFail(index, urlIndex, urlLengths, nextEntty, responseEntity, configEntity, configEntities, url)
			} else {
				if startIndex == configEntity.StartIndex {
					startIndex = nextEntty.Index
				}
				path := configEntity.FileDirPath + "/" + titile + "_ts"
				if util.ExistsDir(path) {
					os.RemoveAll(path)
				}
				//util.Sleep(configEntity, start)
			}
		} else if len(strings.TrimSpace(responseEntity.M3u8)) == 0 {
			flag = false
		} else {
			startIndex = nextEntty.Index
			flag, index, configEntities = downloadFail(index, urlIndex, urlLengths, nextEntty, responseEntity, configEntity, configEntities, url)
		}

	}
	if flag {
		startIndex = nextEntty.Index
		flag, index, configEntities = downloadFail(index, urlIndex, urlLengths, nextEntty, responseEntity, configEntity, configEntities, "url")
	}

	tagTitle := fmt.Sprintf(nextEntty.TitleStrFormat, 11)
	targetFilePath := configEntity.FileDirPath + "/" + tagTitle + configEntity.AudioType
	tsPath := configEntity.FileDirPath + "/" + nextEntty.TitleIndex
	if configEntity.Cover4K == "1" {
		if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, configEntity.FileMinSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
			flag = util.Convert4K(filePath, targetFilePath)

			if flag {
				filePath = targetFilePath
				tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 22)
				targetFilePath = configEntity.FileDirPath + "/" + tagTitle + configEntity.AudioType
				tsPath = configEntity.FileDirPath + "/" + nextEntty.TitleIndex
			}

		}
	}

	sourceSize := util.GetFileSize(filePath) - 80

	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, configEntity.FileMinSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		os.RemoveAll(configEntity.FileDirPath + "/" + nextEntty.TitleIndex)
		os.Mkdir(configEntity.FileDirPath+"/"+nextEntty.TitleIndex, os.ModePerm)

		flag, tsPath = util.SegmentationTs(titile+configEntity.AudioType, configEntity.FileDirPath+"/"+nextEntty.TitleIndex, configEntity, nextEntty.TitleIndex)
		if flag {
			flag = util.CopyFfmpeg(filePath, targetFilePath)
		}
	}

	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 33) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		flag, _ = util.IdentifyImpage(configEntity.FileDirPath+"/"+nextEntty.TitleIndex, configEntity)
		if flag {
			flag = util.CopyFfmpeg(filePath, targetFilePath)
		}
	}

	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 44) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle

	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		flag = util.WatermarkFun(tsPath, configEntity)
		if flag {
			flag = util.CopyFfmpeg(filePath, targetFilePath)
		}
	}
	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 55) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		flag, filePath = util.SysnthesisTsZipToMp4(tagTitle, configEntity, tsPath, configEntity.FileDirPath+"/"+tagTitle)
		//flag = util.CopyFfmpeg(filePath, targetFilePath)
	}

	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 60) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		flag = util.AddBackMusic1(filePath, configEntity, targetFilePath)
		//flag = util.CopyFfmpeg(filePath, targetFilePath)
	}

	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 66) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	sementationPath := configEntity.FileDirPath + "/segmentation/" + nextEntty.TitleStr

	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		var timeVal int
		timeVal, flag = util.GetVideoDuration(filePath)
		if flag {
			flag, sementationPath = util.Segmentation(filePath, timeVal, configEntity, nextEntty, sementationPath)

			if flag {
				flag = util.CopyFfmpeg(filePath, targetFilePath)
			}
		}
	}

	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 77) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		flag = util.MerryGoRoundFun(sementationPath, configEntity, nextEntty.TitleStr)
		if flag {
			flag = util.CopyFfmpeg(filePath, targetFilePath)
		}
	}

	filePath = targetFilePath
	tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 88) + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		//var paths []string
		//flag, paths = util.Synthesis(sementationPath, configEntity)
		//if flag {
		//	flag = util.WriteSend(paths, configEntity.FileDirPath)
		//}
		flag, _ = util.Synthesis(sementationPath, configEntity)

		if flag {
			flag = util.CopyFfmpeg(filePath, targetFilePath)
		}
	}

	//filePath = targetFilePath
	//tagTitle = fmt.Sprintf(nextEntty.TitleStrFormat, 8) + configEntity.AudioType
	//targetFilePath = configEntity.FileDirPath + "/" + tagTitle
	//if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
	//	flag = util.AddBackMusic(sementationPath, configEntity, nextEntty.TitleStr)
	//	if flag {
	//		flag = util.CopyFfmpeg(filePath, targetFilePath)
	//	}
	//}

	filePath = targetFilePath
	tagTitle = nextEntty.TitleNames[0] + configEntity.AudioType
	targetFilePath = configEntity.FileDirPath + "/" + tagTitle

	if flag && !util.ExistsFile(targetFilePath, configEntity) && !util.ValidateFileSize2(targetFilePath, configEntity, sourceSize) && !util.ExistsFile(realFilePath, configEntity) && !util.ValidateFileSize2(realFilePath, configEntity, configEntity.FileMinSize) {
		flag = util.CopyFfmpeg(filePath, targetFilePath)
	}

	if flag {
		removeTempFile(configEntity, nextEntty, 100, sementationPath)
		util.WriteConfigOfStartIndex(configEntity, startIndex, index)
	}
	return flag, index, configEntities, startIndex
}

func removeTempFile(configEntity entity.DownloadEntity, nextEntty entity.PlayListEntity, count int, segmentationPath string) {
	os.RemoveAll(configEntity.FileDirPath + "/" + nextEntty.TitleIndex)

	for i := 0; i < count; i++ {
		tagTitle := fmt.Sprintf(nextEntty.TitleStrFormat, i) + configEntity.AudioType
		targetFilePath := configEntity.FileDirPath + "/" + tagTitle
		os.Remove(targetFilePath)

		targetFilePath = targetFilePath + ".zip.mp4"
		os.Remove(targetFilePath)
	}

	files, _ := ioutil.ReadDir(segmentationPath)
	for _, f := range files {
		if strings.HasSuffix(f.Name(), ".3.mp4") {
			continue
			//os.Remove(segmentationPath + "/" + f.Name())
		} else if strings.HasSuffix(f.Name(), ".mp4") {
			os.Remove(segmentationPath + "/" + f.Name())
		}
	}
}

func downLoad(responseEntity entity.ResponseEntity, configEntity entity.DownloadEntity, titile string, nextEntty entity.PlayListEntity, index int) (bool, []string) {
	flag, filePath := util.FFmpegDownload(responseEntity, configEntity, titile)
	var filePaths []string
	if flag {
		flag, filePaths = util.SwitchFileExsts(nextEntty, filePaths, configEntity)
		if flag {
			flag = false
		} else {
			flag = true
			//time.Sleep(configEntity.ChromedeSleep)
		}

	} else {
		if util.IsNotEmpty(filePath) {
			log.Println("remove", filePath)
			os.Remove(filePath)
		}
		flag = true
	}

	return flag, filePaths
}

func downloadFail(index int, urlIndex int, urlLengths int, nextEntty entity.PlayListEntity, responseEntity entity.ResponseEntity,
	configEntity entity.DownloadEntity, configEntities []string, url string) (bool, int, []string) {
	log.Println("M3u8 error [", responseEntity.M3u8, "],[", responseEntity.TsURL, "]【", index, "]", url)

	index++
	index = cambIndex(index, nextEntty.URLS)

	if urlIndex >= urlLengths {
		configEntities = append(configEntities, url)
	}
	return true, index, configEntities
}

func cambIndex(index int, URLS []string) int {
	if len(URLS) <= index || index < 0 {
		index = 0
	}
	return index
}
